﻿#include "Config.h"
#include "XyNet/Common/System.h"
#include <boost/property_tree/xml_parser.hpp>
#pragma warning(push)
#pragma warning(disable:4715) 
#include <boost/property_tree/json_parser.hpp>
#pragma warning(pop)
#include <boost/property_tree/info_parser.hpp>

namespace XyNet
{
	Config::Config(const string& baseFileName) : _modified(true)
	{
		if (!baseFileName.empty())
			_path = System::getConfigPath() / baseFileName + ".cfg";
		// 因为会调用到纯虚函数loadImpl()，所以不能在这边载入
		//load();
	}

	Config::~Config()
	{
		// 因为会调用到纯虚函数saveImpl()，所以不能析构时保存
		//if (_modified)
		//	save();
	}

	void Config::restoreAllDefaultProperties()
	{
		*_propertyTreeObject.createUniqueLock()->getObject() =
			*_defaultPropertyTreeObject.createSharedLock()->getObject();
	}

	void Config::restoreDefaultProperty(const string& name)
	{
		setProperty(name,
			_defaultPropertyTreeObject.createSharedLock()->getObject()->get<string>(name));
	}

	bool Config::hasProperty(const string& name) const
	{
		auto lock = _defaultPropertyTreeObject.createSharedLock();
		auto defaultPropertyTree = lock->getObject();
		return defaultPropertyTree->find(name) != defaultPropertyTree->not_found();
	}

	const FileSystem::Path& Config::getPath() const
	{
		return _path;
	}

	SharedObject<boost::property_tree::ptree>* Config::getPropertyTreeObject()
	{
		return &_propertyTreeObject;
	}

	void Config::load()
	{
		if (!_path.isEmpty())
		{
			assert(!FileSystem::isDirectory(_path));
			// 如果文件存在则读取
			if (FileSystem::isExists(_path))
			{
				loadImpl();
				_modified = false;
			}
		}
	}

	void Config::save()
	{
		if (_modified && !_path.isEmpty())
		{
			assert(!FileSystem::isDirectory(_path));
			// 如果文件不存在，先创建目录
			if (!FileSystem::isExists(_path))
				FileSystem::createDirectories(_path.getParentPath());
			// 写入文件
			saveImpl();
			_modified = false;
		}
	}

	//void Config::loadImpl() {}

	//void Config::saveImpl() {}

	//////////////////////////////////////////////////////////////////////////

	XmlConfig::XmlConfig(const string& baseFileName /*= ""*/) : Config(baseFileName)
	{
		load();	// 自动载入
	}

	XmlConfig::~XmlConfig()
	{
		save();	// 自动保存
	}

	void XmlConfig::loadImpl()
	{
		boost::filesystem::ifstream fileStream(getPath().getBoostPath());
		boost::property_tree::read_xml(fileStream,
			*getPropertyTreeObject()->createUniqueLock()->getObject());
	}

	void XmlConfig::saveImpl()
	{
		boost::filesystem::ofstream fileStream(getPath().getBoostPath());
		boost::property_tree::write_xml(fileStream,
			*getPropertyTreeObject()->createSharedLock()->getObject(),
			boost::property_tree::xml_writer_make_settings<string>('\t', 1));
	}

	//////////////////////////////////////////////////////////////////////////

	JsonConfig::JsonConfig(const string& baseFileName /*= ""*/) : Config(baseFileName)
	{
		load();	// 自动载入
	}

	JsonConfig::~JsonConfig()
	{
		save();	// 自动保存
	}

	void JsonConfig::loadImpl()
	{
		boost::filesystem::ifstream fileStream(getPath().getBoostPath());
		boost::property_tree::read_json(fileStream,
			*getPropertyTreeObject()->createUniqueLock()->getObject());
	}

	void JsonConfig::saveImpl()
	{
		boost::filesystem::ofstream fileStream(getPath().getBoostPath());
		boost::property_tree::write_json(fileStream,
			*getPropertyTreeObject()->createSharedLock()->getObject());
	}

	//////////////////////////////////////////////////////////////////////////

	InfoConfig::InfoConfig(const string& baseFileName /*= ""*/) : Config(baseFileName)
	{
		load();	// 自动载入
	}

	InfoConfig::~InfoConfig()
	{
		save();	// 自动保存
	}

	void InfoConfig::loadImpl()
	{
		boost::filesystem::ifstream fileStream(getPath().getBoostPath());
		boost::property_tree::read_info(fileStream,
			*getPropertyTreeObject()->createUniqueLock()->getObject());
	}

	void InfoConfig::saveImpl()
	{
		boost::filesystem::ofstream fileStream(getPath().getBoostPath());
		boost::property_tree::write_info(fileStream,
			*getPropertyTreeObject()->createSharedLock()->getObject());
	}
}